package contegor.scire.core.modifications;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import contegor.scire.core.Concept;
import contegor.scire.core.Id;
import contegor.scire.core.IdFragment;
import contegor.scire.core.InfiniteSingletonList;
import contegor.scire.core.Link;
import contegor.scire.core.NeedsPrecedent;
import contegor.scire.core.ReturnPoint;
import contegor.scire.core.ReturnPointDecoratorForErrorsHandling;
import contegor.scire.core.TaskId;
import contegor.scire.core.Version;
import contegor.scire.core.WithSubsequentsExtensible;

/**
 * Base {@link Modification} to create all types of {@link Concept}.
 *
 * @version $Revision$
 * @author  Héctor Cirbián Pousa ($Author$)
 */
@Version("$Id$")
public abstract class BaseCreateConcept<C extends Concept> extends Modification<C> implements WithSubsequentsExtensible<C, Link> {
  private static final long serialVersionUID = 1981529724829704167L;

  protected IdFragment conceptId;
  protected List<NeedsPrecedent<? super C, Link>> subsequents;
  protected C result;

  protected BaseCreateConcept(Id targetContainerId, IdFragment conceptId) {
    super(targetContainerId);
    this.conceptId   = conceptId;
    this.subsequents = null;
    this.result      = null;
  }

  @Override
  public BaseCreateConcept<C> withIt(NeedsPrecedent<? super C, Link> subsequent) {
    if (this.subsequents == null)
      this.subsequents = new LinkedList<NeedsPrecedent<? super C,Link>>();
    this.subsequents.add(subsequent);
    return this;
  }

  @Override
  public List<? extends NeedsPrecedent<? super C, Link>> getSubsequentTasks() {
    if (this.subsequents == null)
      return Collections.emptyList();
    return this.subsequents;
  }

  @Override
  public List<? extends Collection<C>> getResultsForSubsequentTasks() {
    if (this.subsequents == null)
      return Collections.emptyList();
    assert this.result != null;
    return new InfiniteSingletonList<List<C>>(Collections.singletonList(result), this.subsequents.size());
  }

  @Override
  public List<? extends ReturnPoint<Link>> getSubsequentTasksReturnPoints() {
    if (this.subsequents == null)
      return Collections.emptyList();
    return new InfiniteSingletonList<ReturnPoint<Link>>(new ReturnPointDecoratorForErrorsHandling<Link>(this.returnPoint), this.subsequents.size());
  }

  @Override
  public void setTaskId(TaskId taskId) {
    super.setTaskId(taskId);
    if (subsequents != null)
      for (NeedsPrecedent<?,?> subsequent: subsequents)
        subsequent.setTaskId(this.taskId.next(true));
  }
}
